package com.exchange.controller.app.otc;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.aliyun.oss.OSSClient;
import com.exchange.common.model.OtcAdvert;
import com.exchange.common.model.OtcMerchant;
import com.exchange.common.model.OtcOrder;
import com.exchange.common.model.OtcRepresentation;
import com.exchange.common.model.OtcTrust;
import com.exchange.common.model.User;
import com.exchange.common.model.UserPayment;
import com.exchange.common.model.UserWallet;
import com.exchange.common.model.UserWalletFlow;
import com.exchange.constant.BizConst;
import com.exchange.constant.BizConst.KycConst;
import com.exchange.constant.RedisConst;
import com.exchange.interceptor.EnumError;
import com.exchange.util.aliOSSFileUtil;
import com.jfinal.aop.Before;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.jfinal.upload.UploadFile;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

public class OTCService {

	private Cache rides = Redis.use(PropKit.get("redisName"));
	int pageSize = 20;

	/** 商户申请相关 **/
	public Ret apply(User user, String nickName, String reason) {// 申请成为商户
		// 是否已经是
		if (user.getIsOtcMerchant()) {
			return Ret.fail("msg", EnumError.HAS_MERCHANT.getCode());
		}
		// 判断用户是否通过kyc2的认证
		int kyc = user.getVerified();
		if (KycConst.K2_OK != kyc) {
			return Ret.fail("msg", EnumError.C2_V_FAIL.getCode());
		}
		// 判断用户商户记录是否存在,是否已经申请过
		OtcMerchant merchant = OtcMerchant.dao.findFirst("SELECT * FROM t_otc_merchant WHERE userId = ?", user.getId());
		if (BeanUtil.isNotEmpty(merchant) && merchant.getState() == BizConst.MerchantConst.STATE_APPLY) {
			return Ret.fail("msg", EnumError.HAS_APPLY_MERCHANT.getCode());
		}
		// 开始申请
		Date date = new Date();
		if (BeanUtil.isNotEmpty(merchant)) {
			merchant.setState(BizConst.MerchantConst.STATE_APPLY).setNickName(nickName).setReason(reason)
					.setUpdateTime(date).update();
		} else {
			new OtcMerchant().setNickName(nickName).setUserId(user.getId()).setCreateTime(date).setUpdateTime(date)
					.setState(BizConst.MerchantConst.STATE_APPLY).setReason(reason).save();
		}

		return Ret.ok();
	}
	public Ret details(User user) {
		OtcMerchant merchant = OtcMerchant.dao.findFirst("SELECT * FROM t_otc_merchant WHERE userId = ?", user.getId());
		return Ret.ok("merchant", merchant);
	}
	
	
	/** 商户信任相关 **/
	public Ret UserTrustQuery(User user, Integer trustType, Integer pageNumber) {
		Page<OtcTrust> otcTrustPage = OtcTrust.dao.paginate(pageNumber, pageSize, "SELECT * ", "FROM ", user.getId(),
				trustType);
		return Ret.ok("otcTrustPage", otcTrustPage);
	}
	public Ret SetTrust(User user, Integer event, Integer advertId, Integer passiveUserId, Integer type,
			Integer trustId, String reason, String content) {
		Date date = new Date();
		if (event == BizConst.TrustConst.EVENT_ADD) {
			new OtcTrust().setUserId(user.getId()).setAdvertId(advertId).setPassiveUserId(passiveUserId).setType(type)
					.setReason(reason).setContent(content).setCreateTime(date).setUpdateTime(date).save();
		}
		if (event == BizConst.TrustConst.EVENT_DEL) {
			Db.delete("DELETE FROM t_otc_trust WHERE userId = ? AND trustId = ?", user.getId(), trustId);
		}
		if (event == BizConst.TrustConst.EVENT_UP) {
			OtcTrust otcTrust = OtcTrust.dao.findById("trustId");
			otcTrust.setType(type).setUpdateTime(date).update();
		}

		return Ret.ok();
	}
	
	
	/** otc广告相关 **/
	public Ret myOtcAdverts(User user, Integer state, Integer pageNumber) {
		Page<OtcAdvert> otcAdvertPage = OtcAdvert.dao.paginate(pageNumber, pageSize, "SELECT * ",
				"FROM t_otc_advert WHERE state = ? ORDER BY id", state);
		return Ret.ok("otcAdvertPage", otcAdvertPage);
	}
	public Ret advertDetail(Integer advertId) {
		OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND state = 1",
				advertId);
		return Ret.ok("otcAdvert", otcAdvert);
	}
	@Before(Tx.class)
	public Ret advertModify(User user, Integer event, Boolean type, String legalCurrency, String payTypes, String coin,
			BigDecimal price, BigDecimal limitDown, BigDecimal limitUp, String remark, Integer advertId) {
		Prop prop = PropKit.use("parameter.properties");
		// 判断用户是不是商户
		if (!user.getIsOtcMerchant()) {
			return Ret.fail("msg", EnumError.OTC_NOT_MERCHANT.getCode());
		}
    	//判断广告是否需要缴纳保证金,是否超过上限
        JSONObject ADVERTobj = JSONUtil.parseObj(prop.get(BizConst.OtcAdvert.ADVERT_LIMIT_CONFIG));
        BigDecimal limit = NumberUtil.toBigDecimal(ADVERTobj.getStr(legalCurrency));
        //广告上限高于限制，需缴纳保证金
        if(NumberUtil.isGreater(limitUp,limit) && !user.getIsOtcGuarantee()){
        	return Ret.fail("msg", EnumError.OTC_LIMIT_UP.getCode());
        }
		Date date = new Date();
		if (event == BizConst.OtcAdvert.EVENT_ADD) {// 创建
			// 计算用户币的数量(上限/价格)
			BigDecimal num = NumberUtil.div(limitUp, price);
			// 手续费
			JSONObject obj = JSONUtil.parseObj(prop.get(BizConst.OtcAdvert.ADVERT_FEE));
			BigDecimal feeRate = obj.getBigDecimal(coin);
			if (ObjectUtil.isNull(feeRate)) {
				feeRate = obj.getBigDecimal("DEFAULT");
			}
			feeRate = NumberUtil.mul(num, feeRate);
			// 先判断用户钱包够不够
			if (type) {// 卖
				UserWallet userWallet = UserWallet.dao
						.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ? ", user.getId(), coin);
				if (NumberUtil.isGreater(NumberUtil.add(num, feeRate), userWallet.getBalanceOTC())) {
					return Ret.fail("msg", EnumError.WALLET_INSUFFICIENT_FUNDS.getCode());
				}
				// 冻结
				userWallet.setBalanceOTC(NumberUtil.sub(userWallet.getBalanceOTC(), NumberUtil.add(num, feeRate)))
						.setFrozenOTC(NumberUtil.add(userWallet.getFrozenOTC(), NumberUtil.add(num, feeRate)))
						.setVersion(userWallet.getVersion() + 1).setUpdateTime(date);
				userWallet.update();
			}
			// 广告编号
			String advertNumber = StrUtil.toString(System.nanoTime());
			int merchantId = Db.queryInt("SELECT id FROM t_otc_merchant WHERE userId = ?", user.getId());
			OtcAdvert otcAdvert = new OtcAdvert().setMerchantId(merchantId).setType(type).setAdvertNumber(advertNumber)
					.setPrice(price).setLimitUp(limitUp).setLimitDown(limitDown).setCoin(coin).setPayType(payTypes)
					.setUserId(user.getId()).setRemark(remark).setCreateTime(new Date()).setLegalCurrency(legalCurrency)
					.setNum(num).setSurplus(num).setFeeRate(feeRate).setUpdateTime(date);
			otcAdvert.save();
		}
		if (event == BizConst.OtcAdvert.EVENT_DEL) {
			OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND userId = ?", advertId, user.getId());
			if (BeanUtil.isEmpty(otcAdvert)) {
				return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_FIND.getCode());
			}
			if (otcAdvert.getState() != BizConst.OtcAdvert.DISMOUNT) {
				return Ret.fail("msg", EnumError.OTC_ADVERT_NEED_INVALID.getCode());
			}
			otcAdvert.setUpdateTime(date).setState(BizConst.OtcAdvert.dele).update();
		}
		if (event == BizConst.OtcAdvert.EVENT_UP) {
			OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND userId = ?", advertId, user.getId());
			if (BeanUtil.isEmpty(otcAdvert)) {
				return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_FIND.getCode());
			}
			if (otcAdvert.getState() != BizConst.OtcAdvert.DISMOUNT) {
				return Ret.fail("msg", EnumError.OTC_ADVERT_NEED_INVALID.getCode());
			}
			// 计算用户币的数量(上限/价格)
			BigDecimal num = NumberUtil.div(limitUp, price);
			// 手续费
			JSONObject obj = JSONUtil.parseObj(prop.get(BizConst.OtcAdvert.ADVERT_FEE));
			BigDecimal feeRate = obj.getBigDecimal(coin);
			if (ObjectUtil.isNull(feeRate)) {
				feeRate = obj.getBigDecimal("DEFAULT");
			}
			if (type) {// 卖
				UserWallet userWallet = UserWallet.dao
						.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ? ", user.getId(), coin);
				if (NumberUtil.isGreater(NumberUtil.add(num, feeRate), userWallet.getBalanceOTC())) {
					return Ret.fail("msg", EnumError.WALLET_INSUFFICIENT_FUNDS.getCode());
				}
				// 冻结
				userWallet.setBalanceOTC(NumberUtil.sub(userWallet.getBalanceOTC(), NumberUtil.add(num, feeRate)))
						.setFrozenOTC(NumberUtil.add(userWallet.getFrozenOTC(), NumberUtil.add(num, feeRate)))
						.setVersion(userWallet.getVersion() + 1).setUpdateTime(date);
				userWallet.update();
			}
			otcAdvert.setType(type).setPrice(price).setLimitUp(limitUp).setLimitDown(limitDown).setCoin(coin)
					.setPayType(payTypes).setUserId(user.getId()).setRemark(remark).setCreateTime(new Date())
					.setLegalCurrency(legalCurrency).setNum(num).setSurplus(num).setFeeRate(feeRate)
					.setState(BizConst.OtcAdvert.valid).setUpdateTime(date);
			otcAdvert.update();
		}
		return Ret.ok();
	}
	@Before(Tx.class)
	public Ret advertInvalid(User user, Integer advertId) {
		// 判断广告是否存在
		OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND userId = ? AND state = 1", advertId, user.getId());
		if (BeanUtil.isEmpty(otcAdvert)) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_FIND.getCode());
		}
		// 判断此广告是否有正在进行中的订单
		Integer orderCount = Db.queryInt("SELECT COUNT(id) FROM t_otc_order WHERE advertId = ? AND (state = 1 OR state = 3)", advertId);
		if (orderCount != 0) {
			return Ret.fail("msg", EnumError.ADVERT_NOT_TO_BE_INVALID.getCode());
		}
		// 下架逻辑
		Date date = new Date();
		otcAdvert.setState(BizConst.OtcAdvert.DISMOUNT).setUpdateTime(date).setVersion(otcAdvert.getVersion() + 1).update();
		// 若为卖的广告,还要解冻剩余的钱包
		if (otcAdvert.getType()) {
			UserWallet userWallet = UserWallet.dao.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ? ", user.getId(), otcAdvert.getCoin());
			// 当前不退还手续费
//        	BigDecimal takeRate = Db.queryBigDecimal("SELECT SUM(sell_rate) takeRate FROM t_otc_order WHERE advertId = ? AND state = 4", advertId);
			userWallet.setBalanceOTC(NumberUtil.add(userWallet.getBalanceOTC(), otcAdvert.getSurplus()))
					.setFrozenOTC(NumberUtil.sub(userWallet.getFrozenOTC(), otcAdvert.getSurplus()))
					.setVersion(userWallet.getVersion() + 1).setUpdateTime(date).update();
		}

		return Ret.ok();
	}
	public Ret advertList(Integer pageNumber, Boolean type, String coin, String payType, String legalCurrency) {
		String sqlSelect = "SELECT toa.id, toa.userId, toa.type, toa.advertNumber, toa.price, toa.limitUp, toa.limitDown, toa.legalCurrency, toa.payType, toa.state, toa.remark, tom.id merchantId, tom.nickName,(SELECT t.headImage FROM t_user t WHERE t.id = toa.userId) headImg ";
		StringBuffer sqlFrom = new StringBuffer(" FROM t_otc_advert toa JOIN t_otc_merchant tom ON toa.userId = tom.userId WHERE state = 1 ");
		if (ObjectUtil.isNotNull(type)) {
			sqlFrom.append(" AND toa.type = " + type);
		}
		if (StrUtil.isNotBlank(coin)) {
			sqlFrom.append(" AND toa.coin = " + coin);
		}
		if (StrUtil.isNotBlank(payType)) {
			sqlFrom.append(" AND toa.payType = " + payType);
		}
		if (StrUtil.isNotBlank(legalCurrency)) {
			sqlFrom.append(" AND toa.legalCurrency = " + legalCurrency);
		}
		Page<Record> recordPage = Db.paginate(pageNumber, pageSize, sqlSelect, sqlFrom.toString());
		// 获取在线商户
		for (Record r : recordPage.getList()) {
			if (rides.sismember(RedisConst.EXCHANGE_HOLDER_DATA, r.getInt("userId"))) {
				r.set("Online", true);
			} else {
				r.set("Online", false);
			}
		}

		return Ret.ok("advertPage", recordPage);
	}
	
	
	/** OTC订单管理相关 **/
	public Ret otcOrderquery(User user, Integer pageNumber, Boolean type, Integer state) {
		String sqlSelect = "SELECT too.id, too.type, too.coin, too.num, too.orderNumber, too.amount, too.state, too.updateTime, toa.price, toa.legalCurrency ";
		StringBuffer sqlFrom = new StringBuffer(" FROM t_otc_order too JOIN t_otc_advert toa ON too.advertId = toa.id ");
		// 判断用户是否是商户
		if (user.getIsOtcMerchant()) {
			Integer mid = Db.queryInt("SELECT id FROM t_otc_merchant WHERE userId = ?", user.getId());
			sqlFrom.append(" WHERE (too.userId = " + user.getId() + " OR too.merchantId = " + mid + ") ");
		} else {
			sqlFrom.append(" WHERE too.userId = " + user.getId());
		}
		if (ObjectUtil.isNotNull(type)) {
			sqlFrom.append(" AND too.type = " + type);
		}
		if (ObjectUtil.isNotNull(state)) {
			sqlFrom.append(" AND too.type = " + state);
		}
		Page<Record> otcOrderPage = Db.paginate(pageNumber, pageSize, sqlSelect, sqlFrom.toString());

		return Ret.ok("otcOrderPage", otcOrderPage);
	}
	@Before(Tx.class)
	public Ret otcSell(User user, Integer advertId, Boolean type, BigDecimal amount, BigDecimal num, String payType) {
		Prop prop = PropKit.use("parameter.properties");
		// 获取广告详情
		OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND state = 1", advertId);
		if (BeanUtil.isEmpty(otcAdvert)) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_FIND.getCode());
		}
		// 判断参数
		if(!NumberUtil.equals(amount, NumberUtil.mul(num, otcAdvert.getPrice()))) {
			return Ret.fail("msg", EnumError.PARAMETER_ARE_ERROR.getCode());
		}
		// 判断是否是自己的广告
		if (user.getId() == otcAdvert.getUserId()) {
			return Ret.fail("msg", EnumError.USER_NOT_OPERATE_OWN_ADVERT.getCode());
		}
		// 判断要卖给他的数量是不也是广告中需要的数量范围
		if (NumberUtil.isGreater(otcAdvert.getLimitDown(), amount) || NumberUtil.isGreater(amount, otcAdvert.getLimitUp())) {
			return Ret.fail("msg", EnumError.OTC_ORDER_NUM_LACK.getCode());
		}
		// 判断商户是否支持用户选择的支付方式
		Boolean isxt = false;// 是否满足
		String[] otcAdvertPayTypes = otcAdvert.getPayType().split(StrUtil.COMMA);
		for (String otcAdvertPayType : otcAdvertPayTypes) {
			if (StrUtil.equals(otcAdvertPayType, payType)) { isxt = true; break; }
		}
		if (!isxt) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_ALLOW_PAYMENT.getCode());
		}
		// 判断用户当前未支付的订单是否超过限制
		int count = Db.queryInt("SELECT COUNT(id) FROM t_otc_order WHERE state = 1 AND userId = ?", user.getId());
		if (count >= prop.getInt(BizConst.OtcOrder.DEFAULT_OTC_ORDER_APPLY)) {
			return Ret.fail("msg", EnumError.OTC_APPLY_ORDER_TOO_MUCH.getCode());
		}
		// 判断用户在同一广告中是否存在未完成的订单
		int count2 = Db.queryInt("SELECT COUNT(id) FROM t_otc_order WHERE userId = ? AND state IN (1,3) ", user.getId());
		if (count2 > 0) {
			return Ret.fail("msg", EnumError.OTC_ORDER_NOT_COMPLETE.getCode());
		}
		// 判断用户是否支持用户选择的支付方式
		List<UserPayment> userPays = UserPayment.dao.find("SELECT account,address FROM t_user_payment WHERE userId = ? AND payType = ? AND state != 0", user.getId(), payType);
		if (userPays.size() < 1) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_ALLOW_PAYMENT.getCode());
		}
		// 判断用户对应货币钱包可用余额是否足够
		UserWallet userWallet = UserWallet.dao.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ? ",user.getId(), otcAdvert.getCoin());
		JSONObject obj = JSONUtil.parseObj(prop.get(BizConst.OtcAdvert.ADVERT_FEE));
		BigDecimal feeRate = obj.getBigDecimal(otcAdvert.getCoin());// 计算手续费
		if (ObjectUtil.isNull(feeRate)) {
			feeRate = obj.getBigDecimal("DEFAULT");
		}
		feeRate = NumberUtil.mul(num, feeRate);
		BigDecimal znum = NumberUtil.add(num, feeRate);
		if (NumberUtil.isGreater(znum, userWallet.getBalanceOTC())) {
			return Ret.fail("msg", EnumError.WALLET_INSUFFICIENT_FUNDS.getCode());
		}
		// 卖出逻辑
		// 创建订单
		Date date = new Date();
		String payAccount = Db.queryStr("SELECT account FROM t_user_payment WHERE userId = ? AND payType = ? LIMIT 1",
				otcAdvert.getUserId(), payType);
		OtcOrder otcOrder = new OtcOrder().setType(type).setNum(num).setPrice(otcAdvert.getPrice())
				.setState(BizConst.OtcOrder.APPLY).setUserId(user.getId()).setOtherUserId(otcAdvert.getUserId()).setAmount(amount).setAdvertId(advertId)
				.setCoin(otcAdvert.getCoin()).setCreateTime(date).setUpdateTime(date)
				.setLegalCurrency(otcAdvert.getLegalCurrency()).setPayType(payType).setFeeRate(feeRate)
				.setMerchantId(otcAdvert.getMerchantId()).setOrderNumber(StrUtil.toString(System.nanoTime()))
				.setPayAccount(payAccount).setReceiveAccount(userPays.get(0).getAccount())
				.setReceiveAddress(userPays.get(0).getAddress());
		otcOrder.save();
		// 修改钱包冻结
		userWallet.setBalanceOTC(NumberUtil.sub(userWallet.getBalanceOTC(), znum))
				.setFrozenOTC(NumberUtil.add(userWallet.getFrozenOTC(), znum)).setVersion(userWallet.getVersion() + 1)
				.setUpdateTime(date).update();
		// 发送消息
		// TODO 此处要通过ws发送消息,因为还为确认付款,所以不用短信邮箱提醒

		return Ret.ok();
	}
	@Before(Tx.class)
	public Ret otcBuy(User user, Integer advertId, Boolean type, BigDecimal amount, BigDecimal num, String payType) {
		Prop prop = PropKit.use("parameter.properties");
		// 获取广告详情
		OtcAdvert otcAdvert = OtcAdvert.dao.findFirst("SELECT * FROM t_otc_advert WHERE id = ? AND state = 1", advertId);
		if (BeanUtil.isEmpty(otcAdvert)) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_FIND.getCode());
		}
		// 判断参数
		if(!NumberUtil.equals(amount, NumberUtil.mul(num, otcAdvert.getPrice()))) {
			return Ret.fail("msg", EnumError.PARAMETER_ARE_ERROR.getCode());
		}
		// 判断是否是自己的广告
		if (user.getId() == otcAdvert.getUserId()) {
			return Ret.fail("msg", EnumError.USER_NOT_OPERATE_OWN_ADVERT.getCode());
		}
		// 判断要卖给他的数量是不也是广告中需要的数量范围
		if (NumberUtil.isGreater(otcAdvert.getLimitDown(), amount) || NumberUtil.isGreater(amount, otcAdvert.getLimitUp())) {
			return Ret.fail("msg", EnumError.OTC_ORDER_NUM_LACK.getCode());
		}
		// 判断商户是否支持用户选择的支付方式
		Boolean isxt = false;// 是否满足
		String[] otcAdvertPayTypes = otcAdvert.getPayType().split(StrUtil.COMMA);
		for (String otcAdvertPayType : otcAdvertPayTypes) {
			if (StrUtil.equals(otcAdvertPayType, payType)) {isxt = true;break;}
		}
		if (!isxt) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_ALLOW_PAYMENT.getCode());
		}
		// 判断用户当前未支付的订单是否超过限制
		int count = Db.queryInt("SELECT COUNT(id) FROM t_otc_order WHERE state = 1 AND userId = ?", user.getId());
		if (count >= prop.getInt(BizConst.OtcOrder.DEFAULT_OTC_ORDER_APPLY)) {
			return Ret.fail("msg", EnumError.OTC_APPLY_ORDER_TOO_MUCH.getCode());
		}
		// 判断广告中是否存在未完成的订单
		int count2 = Db.queryInt("SELECT COUNT(id) FROM t_otc_order WHERE id = ? AND state IN (1,3) ", otcAdvert.getId());
		if (count2 > 0) {
			return Ret.fail("msg", EnumError.OTC_ORDER_NOT_COMPLETE.getCode());
		}
		// 判断用户是否支持用户选择的支付方式
		List<UserPayment> userPays = UserPayment.dao.find( "SELECT account,address FROM t_user_payment WHERE userId = ? AND payType = ? AND state != 0", user.getId(), payType);
		if (userPays.size() < 1) {
			return Ret.fail("msg", EnumError.OTC_ADVERT_NOT_ALLOW_PAYMENT.getCode());
		}
		// 广告剩余币数量
		if(NumberUtil.isGreater(num, otcAdvert.getSurplus())) {
			return Ret.fail("msg", EnumError.OTC_ORDER_NUM_EXCEED.getCode());
		}
		// 买入逻辑
		// 创建订单
		JSONObject obj = JSONUtil.parseObj(prop.get(BizConst.OtcAdvert.ADVERT_FEE));
		BigDecimal feeRate = obj.getBigDecimal(otcAdvert.getCoin());// 计算手续费
		if (ObjectUtil.isNull(feeRate)) {
			feeRate = obj.getBigDecimal("DEFAULT");
		}
		feeRate = NumberUtil.mul(num, feeRate);
		Date date = new Date();
		UserPayment receiveAccount = UserPayment.dao.findFirst("SELECT account,address FROM t_user_payment WHERE userId = ? AND payType = ? LIMIT 1", otcAdvert.getUserId(), payType);
		OtcOrder otcOrder = new OtcOrder().setType(type).setNum(num).setPrice(otcAdvert.getPrice())
				.setState(BizConst.OtcOrder.APPLY).setUserId(user.getId()).setOtherUserId(otcAdvert.getUserId()).setAmount(amount).setAdvertId(advertId)
				.setCoin(otcAdvert.getCoin()).setCreateTime(date).setUpdateTime(date)
				.setLegalCurrency(otcAdvert.getLegalCurrency()).setPayType(payType).setFeeRate(feeRate)
				.setMerchantId(otcAdvert.getMerchantId()).setOrderNumber(StrUtil.toString(System.nanoTime()))
				.setPayAccount(userPays.get(0).getAccount()).setReceiveAccount(receiveAccount.getAccount())
				.setReceiveAddress(receiveAccount.getAddress());
		otcOrder.save();
		// 修改广告剩余
		otcAdvert.setSurplus(NumberUtil.sub(otcAdvert.getSurplus(), num)).setVersion(otcAdvert.getVersion() + 1).setUpdateTime(date).update();
		//判断剩余的可购买数量是否低于下限，若低于，直接下架广告(去掉这个逻辑,用户自己下架)
		// 发送消息
		// TODO 此处要通过ws发送消息,因为还为确认付款,所以不用短信邮箱提醒

		return Ret.ok();
	}
	@Before(Tx.class)
	public Ret cancelOtcOrder(User user, Integer otcOrderId) {
		//获取订单详情,订单只能是要付钱的一方撤销
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE id = ? AND state = 1", otcOrderId);
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        //我是下单的,//自己下的卖单不能取消,因为下单后对面可能已经打款
        if(user.getId() == otcOrder.getUserId()) {
        	if (otcOrder.getType()) {
            	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_CANCEL.getCode());
            }
        }
        //我是发布的.//自己下的买单不能取消,因为下单后对面可能已经打款
        if(user.getId() == otcOrder.getOtherUserId()) {
        	if (!otcOrder.getType()) {
            	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_CANCEL.getCode());
            }
        }
        //撤销逻辑
        Date date = new Date();
        //获取广告
        OtcAdvert otcAdvert = OtcAdvert.dao.findById(otcOrder.getAdvertId());
        //买单退单
        if (!otcOrder.getType()) {
        	//恢复广告中的数量
        	otcAdvert.setNum(NumberUtil.add(otcAdvert.getNum(), otcOrder.getNum()))
        	.setVersion(otcAdvert.getVersion() + 1).setUpdateTime(date).update();
        } else {//卖单退单
        	//将币解冻
        	UserWallet userWallet = UserWallet.dao.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ? ", user.getId(), otcAdvert.getCoin());
        	userWallet.setBalanceOTC(NumberUtil.add(userWallet.getBalanceOTC(), otcOrder.getNum())).setFrozenOTC(NumberUtil.sub(userWallet.getFrozenOTC(), otcOrder.getNum()));
        	userWallet.setVersion(userWallet.getVersion() + 1).setUpdateTime(date).update();
        }
        //修改订单状态
        otcOrder.setState(BizConst.OtcOrder.cancel).update();
        
        return Ret.ok();
    }
	public Ret isPay(User user, Integer otcOrderId) {
		// 获取订单
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE id = ? AND state = 1", otcOrderId);
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        // 卖币的用户不能点放款
        if(!otcOrder.getType() && user.getId() == otcOrder.getOtherUserId()) {
            return Ret.fail("msg", EnumError.OTC_ORDER_NOT_PAY.getCode());
        }
        if(otcOrder.getType() && user.getId() == otcOrder.getUserId()) {
            return Ret.fail("msg", EnumError.OTC_ORDER_NOT_PAY.getCode());
        }
        // 打款
        Date date = new Date();
        otcOrder.setState(BizConst.OtcOrder.PAYED).setVersion(otcOrder.getVersion() + 1).setUpdateTime(date).update();
        // 发送消息
 		// TODO 此处要通过ws发送消息,短信邮箱提醒
        
        return Ret.ok();

    }
	@Before(Tx.class)
	public Ret otcAdopt(User user, Integer otcOrderId) {
		// 获取订单
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE id = ? AND state = 3", otcOrderId);
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        //判断用户资金密码
        String pwd = SecureUtil.md5( StrUtil.addSuffixIfNot(user.getCipher(), BizConst.BIZ_SECRET_CODE));
        if( !StrUtil.equals( pwd, user.getCipher())){
        	return Ret.fail("msg", EnumError.CIPHER_PASSWORD_ERROR.getCode());
        }
        // 买币的用户不能点放币
        if(!otcOrder.getType() && user.getId() == otcOrder.getUserId()) {
            return Ret.fail("msg", EnumError.OTC_ORDER_NOT_ADOPT.getCode());
        }
        if(otcOrder.getType() && user.getId() == otcOrder.getOtherUserId()) {
            return Ret.fail("msg", EnumError.OTC_ORDER_NOT_ADOPT.getCode());
        }
        // 放币
        // 更新订单状态
        Date date = new Date();
        otcOrder.setState(BizConst.OtcOrder.ADOPT).setVersion(otcOrder.getVersion() + 1).setUpdateTime(date).update();
        // 订单用户钱包
        UserWallet orderUserWallet = UserWallet.dao.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ?", otcOrder.getUserId(), otcOrder.getCoin());
        // 商户钱包
        UserWallet mWallet = UserWallet.dao.findFirst("SELECT * FROM t_user_wallet WHERE userId = ? AND coin = ?", otcOrder.getOtherUserId(), otcOrder.getCoin());        
        if(otcOrder.getType()) { // 卖
            //下单用户,将钱包的冻结部分去掉
        	BigDecimal znum = NumberUtil.add(otcOrder.getNum(), otcOrder.getFeeRate());
        	orderUserWallet.setFrozenOTC(NumberUtil.sub(orderUserWallet.getFrozenOTC(), znum))
        	.setVersion(orderUserWallet.getVersion() + 1).setUpdateTime(date).update();
        	//钱包流
        	new UserWalletFlow().setUserId(otcOrder.getUserId()).setType(BizConst.WalletConst.OTC_SUB)
        	.setAmount(znum).setCoin(otcOrder.getCoin()).setOutFee(otcOrder.getFeeRate())
        	.setFeeCoin(otcOrder.getCoin()).setCreateTime(date).setOriginator(otcOrder.getUserId()).setOrderId(otcOrder.getId())
        	.save();
        	//商户
        	BigDecimal znum2 = NumberUtil.sub(otcOrder.getNum(), otcOrder.getFeeRate());
        	mWallet.setBalanceOTC(NumberUtil.add(mWallet.getBalanceOTC(), znum2))
        	.setVersion(mWallet.getVersion() + 1).setUpdateTime(date).update();
        	//钱包流水
        	new UserWalletFlow().setUserId(otcOrder.getOtherUserId()).setType(BizConst.WalletConst.OTC_ADD)
        	.setAmount(znum2).setCoin(otcOrder.getCoin()).setOutFee(otcOrder.getFeeRate())
        	.setFeeCoin(otcOrder.getCoin()).setCreateTime(date).setOriginator(otcOrder.getOtherUserId()).setOrderId(otcOrder.getId())
        	.save();
        }else { // 买单
        	//下单用户,添加余额
        	BigDecimal znum = NumberUtil.sub(otcOrder.getNum(), otcOrder.getFeeRate());
        	orderUserWallet.setBalanceOTC(NumberUtil.add(orderUserWallet.getBalanceOTC(), znum))
        	.setVersion(orderUserWallet.getVersion() + 1).setUpdateTime(date).update();
        	//钱包流水
        	new UserWalletFlow().setUserId(otcOrder.getUserId()).setType(BizConst.WalletConst.OTC_ADD)
        	.setAmount(znum).setCoin(otcOrder.getCoin()).setOutFee(otcOrder.getFeeRate())
        	.setFeeCoin(otcOrder.getCoin()).setCreateTime(date).setOriginator(otcOrder.getUserId()).setOrderId(otcOrder.getId())
        	.save();
        	//商户
        	BigDecimal znum2 = NumberUtil.add(otcOrder.getNum(), otcOrder.getFeeRate());
        	mWallet.setFrozenOTC(NumberUtil.sub(mWallet.getFrozenOTC(), znum2))
        	.setVersion(mWallet.getVersion() + 1).setUpdateTime(date).update();
        	//钱包流
        	new UserWalletFlow().setUserId(otcOrder.getOtherUserId()).setType(BizConst.WalletConst.OTC_SUB)
        	.setAmount(znum2).setCoin(otcOrder.getCoin()).setOutFee(otcOrder.getFeeRate())
        	.setFeeCoin(otcOrder.getCoin()).setCreateTime(date).setOriginator(otcOrder.getOtherUserId()).setOrderId(otcOrder.getId())
        	.save();
        }
        // 更新商户表
        OtcMerchant otcMerchant = OtcMerchant.dao.findById(otcOrder.getMerchantId());
        if(otcMerchant.getNum() == 0) {//第一次
        	otcMerchant.setNum(1).setFirstTradeTime(date);
        }else {
        	otcMerchant.setNum(otcMerchant.getNum() + 1);
        }
        otcMerchant.setUpdateTime(date).update();
        // 发送消息
      	// TODO 此处要通过ws发送消息,短信邮箱提醒
        
        
        return Ret.ok();
    }
	public Ret otcComment(User user, Integer otcOrderId, String opinion, Integer satisfaction) {
		//获取订单详情
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE id = ? AND userId = ? AND state = 4", otcOrderId, user.getId());
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        Date date = new Date();
        otcOrder.setOpinion(opinion).setSatisfaction(satisfaction).setState(BizConst.OtcOrder.COMMENT).setVersion(otcOrder.getVersion() + 1).setUpdateTime(date).update();
        OtcMerchant otcMerchant = OtcMerchant.dao.findById(otcOrder.getMerchantId());
        //如果评论为 不满意
        if(satisfaction == BizConst.OtcOrder.NSATISFY) {
        	//修改商户表的好评率
        	Double d = (otcMerchant.getPraise() * otcMerchant.getNum() - 1)/otcMerchant.getNum();
        	otcMerchant.setPraise(d).setUpdateTime(date).update();
        }
        if(satisfaction == BizConst.OtcOrder.COMMONLY) {
        	//修改商户表的好评率
        	Double d = (otcMerchant.getPraise() * otcMerchant.getNum() - 0.5)/otcMerchant.getNum();
        	otcMerchant.setPraise(d).setUpdateTime(date).update();
        }
        
        return Ret.ok();
    }
	public Ret otcRepresentation(User user, String orderNumber, Integer type, String reason, List<UploadFile> materials) {
		//获取订单详情
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE orderNumber = ? ", orderNumber);
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        Date date = new Date();
        String imgstr = "";
		for(UploadFile uf : materials) {
			OSSClient ossClient = aliOSSFileUtil.getOSSClient();
	        String picUrl = aliOSSFileUtil.uploadImg(ossClient, uf.getFile(), PropKit.get("bucketApp"));
	        imgstr = imgstr+","+ picUrl;
        }
		new OtcRepresentation().setUserId(user.getId()).setOrderNumber(orderNumber).setType(type).setReason(reason)
		.setMaterial(imgstr).setCreateTime(date).save();
		
        return Ret.ok();
    }
	public Ret otcOrderDetails(User user, Integer otcOrderId) {
		//获取订单详情
		OtcOrder otcOrder = OtcOrder.dao.findFirst("SELECT * FROM t_otc_order WHERE id = ? ", otcOrderId);
        if (BeanUtil.isEmpty(otcOrder) || (user.getId() != otcOrder.getUserId() && user.getId() != otcOrder.getOtherUserId()) ) {
        	return Ret.fail("msg", EnumError.OTC_ORDER_NOT_FIND.getCode());
        }
        User orderUser = User.dao.findById(otcOrder.getUserId());
        User mUser = User.dao.findById(otcOrder.getOtherUserId());
        if(otcOrder.getType()) {// 卖
        	otcOrder.set("sellerName", mUser.getNickName());
        	otcOrder.set("buyerName", orderUser.getNickName());
        	otcOrder.set("sellerImage", mUser.getHeadImage());
        	otcOrder.set("buyerImage", orderUser.getHeadImage());
        	otcOrder.set("sellerTel", mUser.getPhone());
        	otcOrder.set("buyerTel", orderUser.getPhone());
        }else {
        	otcOrder.set("sellerName", orderUser.getNickName());
        	otcOrder.set("buyerName", mUser.getNickName());
        	otcOrder.set("sellerImage", orderUser.getHeadImage());
        	otcOrder.set("buyerImage", mUser.getHeadImage());
        	otcOrder.set("sellerTel", orderUser.getPhone());
        	otcOrder.set("buyerTel", mUser.getPhone());
        }
        
        return Ret.ok("otcOrderDetails", otcOrder);
    }
	
	
	
}
